package com.wang.jmonkey.modules.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.jmonkey.common.model.enums.BooleanEnum;
import com.wang.jmonkey.common.utils.TreeUtil;
import com.wang.jmonkey.modules.system.mapper.SystemAclMapper;
import com.wang.jmonkey.modules.system.mapper.SystemResourceMapper;
import com.wang.jmonkey.modules.system.model.dto.SystemMenuTreeDto;
import com.wang.jmonkey.modules.system.model.dto.SystemModuleResourceDto;
import com.wang.jmonkey.modules.system.model.dto.SystemResourceTreeDto;
import com.wang.jmonkey.modules.system.model.entity.SystemResourceEntity;
import com.wang.jmonkey.modules.system.model.enums.SystemResourceTypeEnum;
import com.wang.jmonkey.modules.system.service.SystemResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.LongStream;

/**
 * 系统资源信息表(SystemResource)表服务实现类
 *
 * @author HeJiawang
 * @since 2021-05-21 21:45:37
 */
@Service
public class SystemResourceServiceImpl extends ServiceImpl<SystemResourceMapper, SystemResourceEntity> implements SystemResourceService {

    /**
     * mapper
     */
    @Autowired
    private SystemResourceMapper mapper;

    @Autowired
    private SystemAclMapper systemAclMapper;

    private Map<SystemResourceTypeEnum, String> RESOURCE_TABLE_MAP = new HashMap<>(){
        {
            put(SystemResourceTypeEnum.Module, "system_module");
            put(SystemResourceTypeEnum.Menu, "system_menu");
            put(SystemResourceTypeEnum.Button, "system_button");
        }
    };

    /**
     * <li>删除资源信息</li>
     * <li>删除子集资源信息</li>
     * <li>删除资源权限信息</li>
     * @param type 资源类型
     * @param resourceId 资源id
     * @return true 删除成功
     */
    @Transactional
    @Override
    public boolean removeByResourceId(SystemResourceTypeEnum type, Long resourceId) {

        // 获取资源信息
        QueryWrapper<SystemResourceEntity> wrapper = new QueryWrapper<>(
                new SystemResourceEntity().setResourceId(resourceId).setType(type)
        );
        SystemResourceEntity resource = super.getOne(wrapper);

        // 删除资源信息
        super.removeById(resource.getId());

        // 删除资源内容信息, 逻辑删除
        mapper.removeResource(RESOURCE_TABLE_MAP.get(type), resourceId);

        // 删除资源权限信息
        systemAclMapper.deleteByResourceId(resource.getId());

        // 删除下级资源
        wrapper = new QueryWrapper<>(
                new SystemResourceEntity().setParentId(resource.getId())
        );
        List<SystemResourceEntity> resourceList = super.list(wrapper);
        if (CollUtil.isNotEmpty(resourceList)) {
            resourceList.forEach(r -> this.removeByResourceId(r.getType(), r.getResourceId()) );
        }

        return true;
    }

    /**
     * 修改资源的上级资源id
     * @param resource 资源信息
     * @return true 修改成功
     */
    @Override
    public boolean updateParentId(SystemResourceEntity resource) {
        return mapper.updateParentId(resource) >= 0;
    }

    /**
     * 获取资源树
     * @param type 系统资源类型
     * @return 资源树信息
     */
    @Override
    public List<SystemResourceTreeDto> tree(SystemResourceTypeEnum type) {
        List<SystemResourceTreeDto> list = mapper.tree(type);
        return TreeUtil.build(list);
    }

    /**
     * 获取用户有权限的资源信息
     * @param userId 用户id
     * @return 资源信息
     */
    @Override
    public List<SystemModuleResourceDto> list(Long userId) {
        List<SystemModuleResourceDto> result = mapper.list(userId);
        if (CollUtil.isEmpty(result)) return result;

        List<SystemMenuTreeDto> menuList = mapper.listMenu(userId);
        if (CollUtil.isEmpty(menuList)) return result;

        result.forEach(module -> {
            List<SystemMenuTreeDto> menuResource = TreeUtil.build(menuList, module.getResourceId());

            List<String> pathList = CollUtil.newArrayList();
            buildMenuList(menuResource, pathList);

            module.setMenuList(menuResource)
                    .setPathList(pathList)
                    .setIndexPath(buildIndexPath(menuResource));
        });

        return result;
    }

    private void buildMenuList(List<SystemMenuTreeDto> menuResource, List<String> pathList) {
        if (CollUtil.isEmpty(menuResource)) return;

        menuResource.forEach(menu -> {
            if (CollUtil.isNotEmpty(menu.getChildren())) {
                buildMenuList(menu.getChildren(), pathList);
            } else {
                pathList.add(menu.getPath());
            }
        });
    }

    private String buildIndexPath(List<SystemMenuTreeDto> menuResource) {

        if (CollUtil.isNotEmpty(menuResource)) {
            for (SystemMenuTreeDto menu : menuResource) {
                if (menu.getIsIndex().compareTo(BooleanEnum.YES) == 0) {
                    return menu.getPath();
                } else {
                    if (CollUtil.isNotEmpty(menu.getChildren())) {
                        return buildIndexPath(menu.getChildren());
                    }
                }
            }
        }

        return StrUtil.EMPTY;
    }
}
